package etcd

import (
	"context"
	"encoding/json"
	"stock_app/models"
	"strings"

	"go.etcd.io/etcd/clientv3"
)

func SaveJob(job *models.Job) (oldJob *models.Job, err error) {
	// etcd的保存key
	jobKey := JOB_SAVE_DIR + job.Name
	// 任务信息json
	var jobValue []byte
	if jobValue, err = json.Marshal(job); err != nil {
		return
	}
	// 保存到etcd
	var putResp *clientv3.PutResponse
	if putResp, err = etcdDb.Kv.Put(context.TODO(), jobKey, string(jobValue), clientv3.WithPrevKV()); err != nil {
		return
	}
	// 如果是更新, 那么返回旧值
	var oldJobObj models.Job
	if putResp.PrevKv != nil {
		// 对旧值做一个反序列化
		if err = json.Unmarshal(putResp.PrevKv.Value, &oldJobObj); err != nil {
			err = nil
			return
		}
		oldJob = &oldJobObj
	}
	return
}

func DeleteJob(name string) (oldJob *models.Job, err error) {
	// etcd中保存任务的key
	jobKey := JOB_SAVE_DIR + name

	// 从etcd中删除它
	var delResp *clientv3.DeleteResponse
	if delResp, err = etcdDb.Kv.Delete(context.TODO(), jobKey, clientv3.WithPrevKV()); err != nil {
		return
	}

	// 返回被删除的任务信息
	var oldJobObj models.Job
	if len(delResp.PrevKvs) != 0 {
		// 解析一下旧值, 返回它
		if err = json.Unmarshal(delResp.PrevKvs[0].Value, &oldJobObj); err != nil {
			err = nil
			return
		}
		oldJob = &oldJobObj
	}
	return
}

func KillJob(name string) (err error) {
	// 通知worker杀死对应任务
	killerKey := JOB_KILLER_DIR + name
	// 让worker监听到一次put操作, 创建一个租约让其稍后自动过期即可
	leaseGrantResp, err := etcdDb.Lease.Grant(context.TODO(), 1)
	if err != nil {
		return
	}
	// 租约ID
	leaseId := leaseGrantResp.ID
	// 设置killer标记
	if _, err = etcdDb.Kv.Put(context.TODO(), killerKey, "", clientv3.WithLease(leaseId)); err != nil {
		return
	}
	return
}

func GetJobList() (job_list []*models.Job, err error) {
	var getResp *clientv3.GetResponse
	// 获取目录下所有任务信息
	if getResp, err = etcdDb.Kv.Get(context.TODO(), JOB_SAVE_DIR, clientv3.WithPrefix()); err != nil {
		return
	}
	// 初始化数组空间
	job_list = make([]*models.Job, 0)
	// len(jobList) == 0

	// 遍历所有任务, 进行反序列化
	for _, kvPair := range getResp.Kvs {
		job := &models.Job{}
		if err = json.Unmarshal(kvPair.Value, job); err != nil {
			err = nil
			continue
		}
		job_list = append(job_list, job)
	}
	return
}

// 提取worker的IP
func ExtractWorkerIP(regKey string) string {
	return strings.TrimPrefix(regKey, JOB_WORKER_DIR)
}

func GetWorkList() (workerArr []string, err error) {
	// 初始化数组
	workerArr = make([]string, 0)
	var getResp *clientv3.GetResponse
	// 获取目录下所有Kv
	if getResp, err = etcdDb.Kv.Get(context.TODO(), JOB_WORKER_DIR, clientv3.WithPrefix()); err != nil {
		return
	}

	// 解析每个节点的IP
	for _, kv := range getResp.Kvs {
		// kv.Key : /cron/workers/192.168.2.1
		workerIP := ExtractWorkerIP(string(kv.Key))
		workerArr = append(workerArr, workerIP)
	}
	return
}
